iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 29
0

今天與工作室的Alvin談到廣告輪播(Banner)這件事情,於是就開啟了今天的主題。


網路上有許多教學,有使用ScrollView,也有使用CollectionView的,因為考慮到之後可能會有點擊事件,我後來選了CollectionView來實作。

--

一開始以為很簡單,沒想到其實不簡單,並且很多細節,這次我先暫時做一個簡易版本的,首先先宣告一個CollectionView以及其他變數:

//儲存螢幕寬度,省得每次都要打很多字
    let width = UIScreen.main.bounds.width
    
    //我先在素材庫存了七張圖片,這是儲存圖片的陣列
    let imageArray: [UIImage] =
        {
            var arr = [UIImage]()
            for i in 1...7
            {
                let image = UIImage(named: String(i))
                arr.append(image!)
            }
            arr.append(UIImage(named: "1")!)
            return arr
        }()
    
    //儲存當下顯示的圖片的索引
    var imageIndex = 0
    
    //宣告一個CollectionView
    var collectionView: UICollectionView!

接著開始設定這個CollectionView:

func setupCollectionView()
    {
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        
        // section與section之間的距離(如果只有一個section,可以想像成frame) 沒影響
        layout.sectionInset = UIEdgeInsets.zero
        
        // cell的寬、高
        layout.itemSize = CGSize(width: width,
                                 height: 200)
        
        // cell與cell的間距
        layout.minimumLineSpacing = CGFloat(integerLiteral: Int(0))
        
        // cell與邊界的間距 沒影響
        //        layout.minimumInteritemSpacing = CGFloat(integerLiteral: 10)
        
        // 滑動方向預設為垂直。注意若設為垂直,則cell的加入方式為由左至右,滿了才會換行;若是水平則由上往下,滿了才會換列
        layout.scrollDirection = UICollectionView.ScrollDirection.horizontal
        
        //        設定collectionView的大小
        let rect = CGRect(x: 0, y: 20, width: width, height: width * (9 / 16))
        self.collectionView = UICollectionView(frame: rect, collectionViewLayout: layout)
        self.collectionView.dataSource = self
        self.collectionView.delegate = self
        self.collectionView.register(MyCell.self, forCellWithReuseIdentifier: "cell")
        self.collectionView.isPagingEnabled = true
        self.collectionView.backgroundColor = .clear
        self.view.addSubview(collectionView)
    }

並且在ViewDidLoad呼叫這個方法:

override func viewDidLoad() {
        super.viewDidLoad()
        setupCollectionView()
    }

另外新增一個Class來管理Cell,我命名為MyCell:

class MyCell: UICollectionViewCell {
    var imageView = UIImageView()
      func setupImageView(){
        imageView.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: 200)
        imageView.backgroundColor = .lightGray
        self.addSubview(imageView)
        }
    override func layoutSubviews() {
        setupImageView()
    }
}

接著遵從UICollectionViewDelegate、UICollectionViewDataSource:

class ViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource 

並且實作因為遵從協議而必須實作的方法:

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        imageArray.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MyCell
        cell.imageView.image = imageArray[indexPath.item]
        return cell
    }

到了這邊,基本上已經可以手動輪播了,但是我們要自動無限輪播,所以我們需要再做一個Timer,讓App可以自動輪播,將這行程式碼加在ViewDidLoad內:

Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(changeBanner), userInfo: nil, repeats: true)

計時器每隔2秒會呼叫changeBanner這個方法,這個方法是我們自己自訂的,程式碼如下:

@objc func changeBanner()
    {
        imageIndex += 1
        let indexPath: IndexPath = IndexPath(item: imageIndex, section: 0)
        if imageIndex < (imageArray.count - 1)
        {
            collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
        }else if imageIndex == imageArray.count
        {
            print("Scroll to zero")
            imageIndex = 0
            collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: false)
            changeBanner()
        }
    }

現在完成了自動輪播功能了,App看起來應該像這樣子,但是這只是很簡易的寫法,並且只有最初的框架,還需要再作修改:
圖片自動輪播


上一篇
Day28-讓Xcode與模擬器並排顯示在同畫面
下一篇
Day30-終於完賽啦之用iOS本地推播來慶祝一下!!
系列文
想知道自己iOS具現化系能力有多強嗎?實作幾個App就知道了30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
ytyubox
iT邦新手 5 級 ‧ 2020-10-14 17:53:19

我之前遇到一個 UX 的狀況,就是在與 banner 互動的時候要暫停輪轉,互動結束的時候等待時差後繼續輪轉。
後來的成果和程式碼都不錯~

你是說例如我現在點著item不放,背景的timer要暫停嗎?現在好像預設都會這樣了,因為我沒有額外寫這個功能,但是只要我點著item不放,timer就暫停,我放開之後timer才會繼續跑

ytyubox iT邦新手 5 級 ‧ 2020-10-15 09:39:18 檢舉

不是,是離開點擊後,重新等時間間隔

我要留言

立即登入留言